/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.giant.bean.authentication;

import com.giant.authentication.Profile;
import com.giant.authentication.User;
import com.giant.entities.pos.PPos;
import com.giant.exceptions.AutenticacionException;
import com.giant.exceptions.OperacionInvalidaException;
import com.giant.services.ServicioGenericoLocal;
import com.giant.services.authentication.ServiceProfileLocal;
import com.giant.services.authentication.ServiceUserLocal;
import java.io.Serializable;
import java.security.Principal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ejb.EJB;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.primefaces.context.RequestContext;

/**
 *
 * @author harold
 */
@ManagedBean
@SessionScoped
public class LoginBean implements Serializable {

    //-----------------------------------------------------------
    // Atributos
    //-----------------------------------------------------------
    /**
     * Nombre del usuario
     */
    private String userName;
    /**
     * Contraseña del usuario
     */
    private String password;
    /**
     * Contraseña del usuario
     */
    private String newPassword;
    /**
     * Contraseña del usuario
     */
    private String verifyPassword;
    /**
     * Usuario de la sesión
     */
    private User user;
     /**
     * Usuario dealer temporal
     */
    private User userDealer;
    /**
     * Relación con la interfaz adecuada para la autenticación de usuarios
     */
    @EJB
    private ServiceUserLocal servicioUser;
    /**
     * Relación con la interfaz adecuada para los perdiles de usuarios
     */
    @EJB
    private ServiceProfileLocal serviceProfile;
    @EJB
    private ServicioGenericoLocal serviceGeneric;
    /**
     * Mensaje de error
     */
    private String mensajeError;
    /**
     * Determina si existe error o no
     */
    private boolean error;
    /**
     * Determina si el usuario esta logeado o no
     */
    private boolean loggedIn = false;
    /**
     * Perfil seleccionado
     */
    private Integer selectedProfile = 0;
    /**
     *
     */
    private boolean visiblePanel = false;
    /**
     * Determina si el perfil del usuario logeado es POS
     */
    private boolean isPOS = false;
    /**
     * Si el perfil es POS, guardara el pos que tenga parametrizado el usuario
     */
    private PPos currentPos;
    /**
     * Determines if the authorized profile is admin
     */
    private boolean isAdmin = false;
    //-----------------------------------------------------------
    // Constructor
    //-----------------------------------------------------------

    /**
     * Constructor de la clase
     */
    public LoginBean() {
        error = false;
        userDealer= new User();
    }

    //-----------------------------------------------------------
    // Métodos
    //-----------------------------------------------------------
    /**
     * Realiza la autenticación de un usuario que desea entrar al sistema
     *
     * @return tipoUsuario Devuelve el tipo de usuario
     */
    @Deprecated
    public void ingresar(ActionEvent actionEvent) {

        RequestContext context = RequestContext.getCurrentInstance();
        ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
        FacesMessage msg = null;

        try {
            user = servicioUser.ingresar(userName, password);
            if (user != null) {
                loggedIn = true;
                msg = new FacesMessage(FacesMessage.SEVERITY_WARN, "Welcome", user.getUserName());
                System.out.println("User Logged-->" + user.getUserName());
            }
        } catch (Exception ex) {
            loggedIn = false;
            msg = new FacesMessage(FacesMessage.SEVERITY_WARN, "Login Error", "Invalid credentials");
        }

        Map<String, Object> sessionMap = externalContext.getSessionMap();
        sessionMap.put("loggedIn", loggedIn);
        sessionMap.put("user", user);

        FacesContext.getCurrentInstance().addMessage(null, msg);
        context.addCallbackParam("loggedIn", loggedIn);

    }

    /**
     * Authentication method for any user
     */
    public void login() {
        HttpServletRequest request = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
        RequestContext context = RequestContext.getCurrentInstance();
        ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
        FacesMessage msg = null;

        try {
            //Login via the Servlet Context
            request.login(userName, password);
            //Retrieve the Principal User
            Principal principal = request.getUserPrincipal();
            //Get user
            user = servicioUser.ingresar(userName, password);

            if (request.getUserPrincipal() != null && user != null) {
                loggedIn = true;
                //Add the welcome message to the faces context
                msg = new FacesMessage(FacesMessage.SEVERITY_WARN, "Welcome", principal.getName());
                System.out.println("User Logged-->" + principal.getName());
            }

        } catch (ServletException e) {
            loggedIn = false;
            msg = new FacesMessage(FacesMessage.SEVERITY_WARN, "Login Error", "Invalid credentials " + e.getMessage());
        } catch (AutenticacionException ex) {
            loggedIn = false;
            msg = new FacesMessage(FacesMessage.SEVERITY_WARN, "Login Error", "Invalid credentials");
        }
        //set global atributtes
        Map<String, Object> sessionMap = externalContext.getSessionMap();
        sessionMap.put("loggedIn", loggedIn);
        sessionMap.put("user", user);
        sessionMap.put("isAdmin", isAdmin);
        //register dealers for logged user
        getDealersByUser();
        //set authentication message
        FacesContext.getCurrentInstance().addMessage(null, msg);
        //select default user_pos profile
        if (request.isUserInRole("USER_POS")) {
            List<Profile> tmp = getUserProfiles();
            for (int i = 0; i < tmp.size(); i++) {
                Profile profile = tmp.get(i);
                if (profile.getName().equals("USER_POS")) {
                    selectedProfile = profile.getIdProfile();
                }
            }
            isPOS = true;
            currentPos = servicioUser.getUserPos(user);
            sessionMap.put("pos", currentPos);
            sessionMap.put("profile", getSelectedProfile());
            System.out.println("User Profile-->" + getSelectedProfile());
        }
        //Set external atributtes
        context.addCallbackParam("loggedIn", loggedIn);
        context.addCallbackParam("isPOS", isPOS);
    }

    public String changePassword() {
        String ret = "homePage";
        boolean changed = false;
        RequestContext context = RequestContext.getCurrentInstance();

        FacesMessage msg = null;
        try {

            if (newPassword.equals(verifyPassword)) {
                changed = servicioUser.changePassword(context.getCallbackParams().get("username") + "", password, newPassword);
            }
            if (changed) {
                msg = new FacesMessage(FacesMessage.SEVERITY_INFO, "Password Changed", userName);
                ret = "homePage";

            } else {
                msg = new FacesMessage(FacesMessage.SEVERITY_WARN, "Password Change Error", "Invalid password");
            }

        } catch (Exception ex) {
            msg = new FacesMessage(FacesMessage.SEVERITY_WARN, "Password Change Error", "Invalid password");
        }
        FacesContext.getCurrentInstance().addMessage(null, msg);
        return ret;

    }

    /**
     * Cierra el panel de error
     */
    public void cerrarPanelError() {
        error = false;
        mensajeError = null;
    }

    /**
     * Realiza un logout de la sesión del cliente
     *
     * @return login Devuelve a la página de inicio
     */
    public void logout() {

        System.out.println("logout2");
        HttpSession session = (HttpSession) FacesContext.getCurrentInstance().getExternalContext().getSession(false);
        if (session != null) {
            session.invalidate();
        }
        FacesContext.getCurrentInstance().getApplication().getNavigationHandler().handleNavigation(FacesContext.getCurrentInstance(), null, "/Authentication.xhtml");

    }

    /**
     * Return profiles for logged user
     *
     * @return
     */
    public List<Profile> getUserProfiles() {
        List<Profile> profiles = new ArrayList<Profile>();
        if (loggedIn) {
            //serviceProfile
            String sql = "select p.* from user_profile up join profile p on up.id_profile=p.id_profile where p.status=1 and up.id_user=" + user.getIdUser();
            profiles = serviceProfile.getProfiles(sql);
        }
        return profiles;
    }

    /**
     * Return the dealers of the logged user
     * @return
     */
    public List<User> getDealersByUser() {
        List<User> users = new ArrayList<User>();
        ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
        Map<String, Object> sessionMap = externalContext.getSessionMap();
        
        if (loggedIn) {
            String sql = "select u.* from user_dealer ud join user u on ud.id_dealer=u.id_user where ud.id_user=" + user.getIdUser();
            users = serviceGeneric.getList(sql, User.class);
            sessionMap.put("dealers", users);
        }
        return users;
    }

    /**
     * Selects the user profile
     *
     * @return
     */
    public String selectProfile() {
        ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
        Map<String, Object> sessionMap = externalContext.getSessionMap();
        sessionMap.put("profile", getSelectedProfile());
        //set if admin profile is selected
        List<Profile> tmp = getUserProfiles();
        for (int i = 0; i < tmp.size(); i++) {
            Profile profile = tmp.get(i);
            if (profile.getIdProfile() == getSelectedProfile()) {
                if (profile.getName().equals("ADMIN")) {
                    isAdmin = true;
                }
            }
        }
        sessionMap.put("isAdmin", isAdmin);
        System.out.println("User Profile-->" + getSelectedProfile());
        return "homePage";
    }
    
    public void createUserDealer()
    {
        try {
            //userDealer.setStatus(true);
            //servicioUser.agregarUser(userDealer);
            String sql="INSERT INTO user(id_user, user_name, password, email, num_doc, status) VALUES (null,'"+userDealer.getUserName()+"',sha ('" + userDealer.getPassword() + "') , '"+userDealer.getEmail()+"',"+userDealer.getNumDoc()+",1)";
            serviceGeneric.executeGenericSQLAdd(sql);
            sql ="INSERT INTO user_dealer(id_user, id_dealer) select "+user.getIdUser()+", max(id_user) from user";
            serviceGeneric.executeGenericSQLAdd(sql);
            sql="INSERT INTO user_profile(id_user, id_profile) select max(id_user), 2 from user";
            serviceGeneric.executeGenericSQLAdd(sql);
            //clean user data
            userDealer= new User();
        } catch (Exception ex) {
            Logger.getLogger(LoginBean.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    //-----------------------------------------------------------
    // Getters y setters
    //-----------------------------------------------------------
    public List<User> getUsers() {
        return servicioUser.getUser();
    }

    /**
     * Devuelve el nombre del usuario
     *
     * @return usuario Nombre del usuario
     */
    public String getUserName() {
        return userName;
    }

    /**
     * Modifica el nombre del usuario
     *
     * @param usuario Nuevo nombre del usuario
     */
    public void setUserName(String user) {
        this.userName = user;
    }

    /**
     * Devuelve la contraseña del usuario
     *
     * @return contraseña Contraseña del usuario
     */
    public String getPassword() {
        return password;
    }

    /**
     * Modifica la contraseña de un usuario
     *
     * @param contraseña Nueva contraseña
     */
    public void setPassword(String password) {
        this.password = password;
    }

    /**
     * Usuario a quien pertenece la sesión
     *
     * @return sesion Usuario a quien pertenece la sesión
     */
    public User getUser() {
        return user;
    }

    /**
     * Modifica el usuario de la sesión
     *
     * @param sesion Nuevo usuario
     */
    public void setUser(User user) {
        this.user = user;
    }

    /**
     * Devuelve el estado de la autenticación (si es error o no)
     *
     * @return error Estado de autenticación
     */
    public boolean isError() {
        return error;
    }

    /**
     * Modifica el estado de error
     *
     * @param error Nuevo estado
     */
    public void setError(boolean error) {
        this.error = error;
    }

    /**
     * Devuelve un mensaje de error
     *
     * @return mensaje Mensaje de error
     */
    public String getMensajeError() {
        return mensajeError;
    }

    /**
     * Modifica el mensaje de error
     *
     * @param mensajeError Nuevo mensaje de error
     */
    public void setMensajeError(String mensajeError) {
        this.mensajeError = mensajeError;
    }

    public String getNewPassword() {
        return newPassword;
    }

    public void setNewPassword(String newPassword) {
        this.newPassword = newPassword;
    }

    public String getVerifyPassword() {
        return verifyPassword;
    }

    public void setVerifyPassword(String verifyPassword) {
        this.verifyPassword = verifyPassword;
    }

    public Integer getSelectedProfile() {
        return selectedProfile;
    }

    public void setSelectedProfile(Integer selectedProfile) {
        this.selectedProfile = selectedProfile;
    }

    public boolean isVisiblePanel() {
        return visiblePanel;
    }

    public void setVisiblePanel(boolean visiblePanel) {
        this.visiblePanel = visiblePanel;
    }

    public void changePanelVisibility() {
        visiblePanel = !visiblePanel;
    }

    public boolean isIsPOS() {
        return isPOS;
    }

    public void setIsPOS(boolean isPOS) {
        this.isPOS = isPOS;
    }

    public String getPath() {
        if (isPOS) {
            return "pos";
        }
        return "user";
    }

    public boolean isIsAdmin() {
        return isAdmin;
    }

    public void setIsAdmin(boolean isAdmin) {
        this.isAdmin = isAdmin;
    }

    public User getUserDealer() {
        return userDealer;
    }

    public void setUserDealer(User userDealer) {
        this.userDealer = userDealer;
    }
    
}
